package com.question.dicegame;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Rectangle2D;
import java.io.File;
import java.net.URL;
import java.util.ArrayList;

import javax.imageio.ImageIO;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

public class DiceGameBoard extends JPanel implements Runnable {

	// 게임 객체들이 사용할 이미지
	private Image[] playerImage;
	private Image mapImage;
	private Image diceImage;
	private Image itemImage;

	// 게임 객체 클래스
	private Dice dice;
	private Player player;
	private Computer computer;

	// 마우스를 눌렀을 때 위치를 저장하기 위한 변수
	private Point startPoint = null;
	private Point endPoint = null;
	// int[] : 셀위치 (x,y)
	// private int[][] player;

	private Font font;
	int number = 0;
	private int flag = 0;
	private ArrayList<int[]> items;
	// 쓰레드와 게임의 시작, 종료를 관리하기 위한 변수
	Thread thread = new Thread(this);
	boolean running;
	private int count;
	private long speed = 1000;
	private long lastAnimatedTime;

	public DiceGameBoard() {
		try {
			URL url = getClass().getResource("map.jpg");
			Image originalImage = ImageIO.read(url);

			mapImage = originalImage.getScaledInstance(Constants.FRAME_WIDTH,
					Constants.FRAME_HEIGHT, Image.SCALE_SMOOTH);

			playerImage = new Image[2];
			for (int i = 0; i < playerImage.length; i++) {
				url = getClass().getResource("player" + i + ".png");
				originalImage = ImageIO.read(url);
				playerImage[i] = originalImage;
			}

			url = getClass().getResource("dice.png");
			originalImage = ImageIO.read(url);
			diceImage = originalImage;

			url = getClass().getResource("item.png");
			originalImage = ImageIO.read(url);
			itemImage = originalImage.getScaledInstance(Constants.CELL_WIDTH,
					Constants.CELL_HEIGHT, Image.SCALE_SMOOTH);

		} catch (Exception ex) {
		}

		setBackground(Color.black);
		setDoubleBuffered(true);

		// 게임 객체 생성
		items = new ArrayList<int[]>();
		player = new Player(playerImage[0], 5);
		computer = new Computer(playerImage[1], 5);
		dice = new Dice(diceImage, 6);
		font = new Font("나눔고딕코딩", Font.BOLD, 20);


		// 배경음
		play("dreams.wav");
		
		addMouseListener(screenMouseHandler);
		// 키보드 이벤트 처리기 등록
		addKeyListener(keyHandler);

		startGame();

	}

	private void startGame() {

		count = 0;

		if (items.size() > 0)
			items.removeAll(items);

		for (int i = 0; i < 10; i++) {
			int[] item = new int[2];
			item[0] = (int) (Math.random() * 10);
			item[1] = (int) (Math.random() * 10);
			items.add(i, item);
		}

		Thread thread = new Thread(this);
		thread.start();

	}

	// 화면의 갱신이 필요할 때 호출되는 메서드 -> 출력을 처리하는 메서드
	@Override
	public void paint(Graphics g) {
		// TODO Auto-generated method stub
		super.paint(g);

		Graphics2D g2d = (Graphics2D) g;

		Image image = null;
		image = mapImage;
		g2d.drawImage(image, 0, 0, Constants.FRAME_WIDTH,
				Constants.FRAME_HEIGHT, this);

		player.draw(g2d, number, flag);
		computer.draw(g2d, number, flag);
		dice.draw(g2d, number);

		for (int i = 0; i < items.size(); i++) {
			int[] obj = items.get(i);
			g2d.drawImage(itemImage, obj[0] * Constants.CELL_WIDTH, obj[1]
					* Constants.CELL_HEIGHT, Constants.CELL_WIDTH,
					Constants.CELL_HEIGHT, this);
		}

		g2d.setFont(font);
		g2d.setColor(Color.gray);
		g2d.drawString("SCORE : " + count, 840, 100);

		g2d.setFont(font);
		g2d.setColor(Color.ORANGE);

		if (flag == 0) {
			g2d.drawString("플레이어 턴", 840, 40);
		} else {
			g2d.drawString("컴퓨터 턴", 840, 40);
		}

		if (!running) {
			g2d.setFont(font);
			Rectangle2D r = g2d.getFontMetrics().getStringBounds("Game Over",
					g2d);
			g2d.setColor(Color.black);
			g2d.drawString("Game OVER",
					(Constants.SCREEN_WIDTH - (int) r.getWidth()) / 2,
					(Constants.SCREEN_HEIGHT - (int) r.getHeight()) / 2);
		}
	}

	@Override
	public void run() {
		running = true;

		while (running) {
			if (!running) {
				repaint();
				break;
			}

			if (number != 0) {
				if (flag == 0) {
					for (int i = 0; i < number * 8; i++) {
						player.movePaint(number);
						repaint();
						try {
							Thread.sleep(30);
						} catch (Exception ex) {
						}
					}
					itemEvent();
					running = player.moveEvent();
					itemEvent();
					flag = 1;
					number = 0;
					lastAnimatedTime = System.currentTimeMillis();
				} else if (flag == 1) {
					for (int i = 0; i < (number) * 8; i++) {
						computer.movePaint(number);
						repaint();
						try {
							Thread.sleep(30);
						} catch (Exception ex) {
						}
					}
					itemEvent();
					running = computer.moveEvent();
					itemEvent();
					flag = 0;
					number = 0;
				}
			}

			// 컴퓨터 프로세스
			if (flag == 1) {
				long current = System.currentTimeMillis();
				if (current - lastAnimatedTime > speed) {
					lastAnimatedTime = current;
					number = (int) ((Math.random() * 6) + 1);
					System.out.println("컴퓨터 : " + number);
				}
			}
			// draw
			repaint();
			try {
				Thread.sleep(30);
			} catch (Exception ex) {
			}

		}
	}

	// TODO sound
	// 소리를 낼 클래스

	// 소리를 낼 메소드, 파일 이름을 인자로 받는다.
	public static synchronized void play(final String fileName) {
		// 소리를 낼 때마다 하나의 쓰레드를 만든다.
		// 이 쓰레드는 소리가 끝나면 소멸한다.
		new Thread(new Runnable() {
			public void run() {
				try {
					Clip clip = AudioSystem.getClip();
					AudioInputStream inputStream = AudioSystem
							.getAudioInputStream(new File(fileName));
					clip.open(inputStream);
					clip.start();
				} catch (Exception e) {
				}
			}
		}).start();
	}

	private MouseAdapter screenMouseHandler = new MouseAdapter() {
		@Override
		public void mousePressed(MouseEvent e) {
			startPoint = e.getPoint();
		}

		@Override
		public void mouseReleased(MouseEvent e) {
			endPoint = e.getPoint();

			if (startPoint.x >= 840 && startPoint.x <= 920
					&& startPoint.y >= 560 && startPoint.y <= 640
					&& endPoint.x >= 840 && endPoint.x <= 920
					&& endPoint.y >= 560 && endPoint.y <= 640 && flag == 0) {
				if(number != 0){
					 return;
				 }
				 number = (int) ((Math.random() * 6) + 1);
				System.out.println("플레이어 :" + number);
			}
			startPoint = null;
			endPoint = null;
		}
	};

	public void itemEvent() {
		for (int i = 0; i < items.size(); i++) {
			if ((player.getX() == items.get(i)[0] * 80
					&& player.getY() == items.get(i)[1] * 80)
					|| (computer.getX() == items.get(i)[0] * 80
					&& computer.getY() == items.get(i)[1] * 80)) {
				if (flag == 0)
					count += 100;

				items.remove(items.get(i));
			}
		}
	}
	
	private KeyAdapter keyHandler = new KeyAdapter() {

		@Override
		public void keyPressed(KeyEvent e) {
			switch (e.getKeyCode()) {
			case KeyEvent.VK_ESCAPE:
				System.out.println("@312321");
				// 게임종료
				String[] buttons = { "다시하기", "종료", "취소" };
				int result = JOptionPane.showOptionDialog(DiceGameBoard.this,
						"종료", "종료 하시겠습니까?", JOptionPane.YES_NO_CANCEL_OPTION,
						JOptionPane.QUESTION_MESSAGE, null, buttons, "취소");
				System.out.println(result);
				switch (result) {
				case 0:
					running = false;
					break;
				case 1:
					System.exit(0);
					break;
				default:
					break;
				}
			}
			super.keyPressed(e);
		}
	};
}
